package jp.seraph.same.model;

import java.io.IOException;
import java.util.List;

import org.apache.commons.lang.NullArgumentException;

import jp.seraph.jsade.model.JointIdentifierContainer;
import jp.seraph.jsmf.codec.LinkMotionUtils;
import jp.seraph.jsmf.codec.FileMotionManager;
import jp.seraph.jsmf.codec.PoseNameLinkMotionElement;
import jp.seraph.jsmf.motion.DefaultMotion;
import jp.seraph.jsmf.motion.EditableMotion;
import jp.seraph.jsmf.motion.Motion;
import jp.seraph.jspf.pose.PoseManager;

public class DefaultMotionCollectionModel implements MotionCollectionModel {
    public DefaultMotionCollectionModel(FileMotionManager aMotionManager, PoseManager aPoseManager, JointIdentifierContainer aIdContainer, PoseCollectionModel aPoseCollectionModel, String aStartMotionName) {
        if(aMotionManager == null)
            throw new NullArgumentException("aMotionManager");
        if(aPoseManager == null)
            throw new NullArgumentException("aPoseManager");
        if(aIdContainer == null)
            throw new NullArgumentException("aIdContainer");
        if(aPoseCollectionModel == null)
            throw new NullArgumentException("aPoseCollectionModel");
        if(aStartMotionName == null)
            throw new NullArgumentException("aStartMotionName");
        
        mMotionManager = aMotionManager;
        mPoseManager = aPoseManager;
        mPoseCollectionModel = aPoseCollectionModel;
        mIdContainer = aIdContainer;
        if(!mMotionManager.containsMotion(aStartMotionName))
            mMotionManager.setMotion(aStartMotionName, new DefaultMotion());

        mMotionNames = mMotionManager.getMotionNames();
        mSelectedMotionModel = new DefaultMotionModel(aStartMotionName,mMotionManager, mPoseManager, mIdContainer, mPoseCollectionModel);
        mSelectedMotionIndex = -1;
    }

    private FileMotionManager mMotionManager;
    private PoseManager mPoseManager;
    private PoseCollectionModel mPoseCollectionModel;
    private List<String> mMotionNames;
    private MotionModel mSelectedMotionModel;
    private int mSelectedMotionIndex;
    private JointIdentifierContainer mIdContainer;

    /**
     *
     * @see jp.seraph.same.model.MotionCollectionModel#getMotion(int)
     */

    public MotionModel getMotion(int aIndex) {
        return this.getMotion(mMotionNames.get(aIndex));
    }

    /**
     *
     * @see jp.seraph.same.model.MotionCollectionModel#getMotion(java.lang.String)
     */

    public MotionModel getMotion(String aMotionName) {
        return new DefaultMotionModel(aMotionName, mMotionManager, mPoseManager, mIdContainer, mPoseCollectionModel);
    }

    /**
     *
     * @see jp.seraph.same.model.MotionCollectionModel#getMotionCount()
     */

    public int getMotionCount() {
        return mMotionNames.size();
    }

    /**
     *
     * @see jp.seraph.same.model.MotionCollectionModel#getMotionName(int)
     */

    public String getMotionName(int aIndex) {
        return mMotionNames.get(aIndex);
    }

    /**
     *
     * @see jp.seraph.same.model.MotionCollectionModel#getSelectedMotion()
     */

    public MotionModel getSelectedMotion() {
        return mSelectedMotionModel;
    }

    /**
     *
     * @see jp.seraph.same.model.MotionCollectionModel#getSelectedIndex()
     */

    public int getSelectedIndex() {
        return mSelectedMotionIndex;
    }

    /**
     *
     * @see jp.seraph.same.model.MotionCollectionModel#getSelectedMotionName()
     */

    public String getSelectedMotionName() {
        if (mSelectedMotionIndex == -1)
            return "";

        return mMotionNames.get(mSelectedMotionIndex);
    }

    /**
     *
     * @see jp.seraph.same.model.MotionCollectionModel#selectMotion(int)
     */

    public void selectMotion(int aIndex) {
        mSelectedMotionIndex = aIndex;
        mSelectedMotionModel = this.getMotion(aIndex);
    }

    /**
     *
     * @see jp.seraph.same.model.MotionCollectionModel#selectMotion(java.lang.String)
     */

    public void selectMotion(String aMotionName) {
        int tIndex = mMotionNames.indexOf(aMotionName);
        if (tIndex == -1)
            throw new IllegalArgumentException("モーション " + aMotionName + " が存在しません．");

        this.selectMotion(tIndex);
    }

    /**
     *
     * @see jp.seraph.same.model.MotionCollectionModel#setMotion(java.lang.String,
     *      jp.seraph.jsmf.codec.PoseNameLinkMotion)
     */
    public void setMotion(String aMotionName, EditableMotion aMotion) {
        if (!mMotionManager.containsMotion(aMotionName)) {
            mMotionNames.add(aMotionName);
        }
        mMotionManager.setMotion(aMotionName, aMotion);
    }

    /**
     *
     * @see jp.seraph.same.model.MotionCollectionModel#setMotion(java.lang.String,
     *      jp.seraph.same.model.MotionModel)
     */

    public void setMotion(String aMotionName, MotionModel aMotion) {
        this.setMotion(aMotionName, aMotion.toMotion());
    }

    /**
     *
     * @see jp.seraph.same.model.MotionCollectionModel#removeMotion(java.lang.String)
     */

    public void removeMotion(String aMotionName) {
        String tSelectedName = this.getSelectedMotionName();
        if (tSelectedName.equals(aMotionName)) {
            mSelectedMotionIndex = -1;
        }
        if (mMotionManager.removeMotion(aMotionName))
            mMotionNames.remove(aMotionName);
    }

    /**
     *
     * @see jp.seraph.same.model.MotionCollectionModel#save()
     */

    public void save() throws IOException {
        mMotionManager.save();
    }

}
